package SquarePackage;

import static org.junit.Assert.*;

import java.math.BigDecimal;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import Border.Door;
import Border.Wall;


public class Squaretest {

	/**
	 * @throws java.lang.Exception
	 */
	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
	}

	/**
	 * @throws java.lang.Exception
	 */
	@AfterClass
	public static void tearDownAfterClass() throws Exception {
	}

	private Wall testWall;
	private Door testDoor;

	/**
	 * @throws java.lang.Exception
	 */
	@Before
	public void setUp() throws Exception {
		testSquare = new Square(200, new BigDecimal(20));
		mergeTestSquare =  new Square(200, new BigDecimal(60));
		testWall = new Wall(testSquare, Direction.NORTH);
		testDoor = new Door(testSquare, Direction.EAST);

	}

	/**
	 * @throws java.lang.Exception
	 */
	@After
	public void tearDown() throws Exception {
	}

	public Square testSquare;
	public Square mergeTestSquare;


	@Test 
	public final void setTemperatureTest(){
		testSquare.setTemperature(200);
		assertEquals(200, testSquare.getTemp(),0);         
	}
	@Test (expected = IllegalArgumentException.class)
	public final void setTemperatureTooHighTest(){
		testSquare.setTemperature(5001);
	}
	@Test (expected = IllegalArgumentException.class)
	public final void setTemperatureNegativeTest(){
		testSquare.setTemperature(-201);
	}
	@Test
	public final void setBorderLegalCaseTest(){
		testSquare.setBorder(Direction.NORTH, testWall);
		assertEquals(true, testSquare.hasBorder(Direction.NORTH));
		assertEquals(3, testSquare.numberOfBorders(testSquare.getBorders()));
	}
	@Test	(expected = IllegalArgumentException.class)
	public final void setBorderIllegalCaseTest(){
		testSquare.setBorder(null, testWall);
		testSquare.setBorder(Direction.NORTH, null);
		assertEquals(2, testSquare.numberOfBorders(testSquare.getBorders()));
	}
	@Test
	public final void setBordersLegalTestCase(){
		testSquare.setBorder(Direction.NORTH,testWall);
		testSquare.setBorder(Direction.EAST, testDoor);
		testSquare.setWall(Direction.CEILING);
		testSquare.setDoor(Direction.WEST);
		assertTrue(testSquare.hasBorder(Direction.EAST));
		assertTrue(testSquare.hasBorder(Direction.NORTH));
		assertTrue(testSquare.hasBorder(Direction.CEILING));
		assertTrue(testSquare.hasBorder(Direction.WEST));
		assertEquals(5, testSquare.numberOfBorders(testSquare.getBorders()));
	}

	@Test
	public final void setBordersMaximumTest(){
		setAllWalls();
		assertEquals(6, testSquare.numberOfBorders(testSquare.getBorders()));
	}
	public void setAllWalls(){
		
		for(Direction direction : Direction.values()){
			testSquare.removeBorder(direction);
			testSquare.setBorder(direction, new Wall(testSquare,direction));
		}
	}
	@Test 
	public final void removeBorderLegalCaseTest(){
		testSquare.setBorder(Direction.NORTH,testWall);
		testSquare.removeBorder(Direction.NORTH);
		assertEquals(2, testSquare.numberOfBorders(testSquare.getBorders()));
		assertFalse( testSquare.hasBorder(Direction.NORTH));
	}
	@Test
	public final void removeBordersLegalCaseTest(){
		setAllWalls();
		testSquare.removeBorders(Direction.NORTH);
		testSquare.removeBorder(Direction.CEILING);
		assertEquals(4, testSquare.numberOfBorders(testSquare.getBorders()));
		assertFalse(testSquare.hasBorder(Direction.NORTH));
		assertTrue( testSquare.hasBorder(Direction.SOUTH));
		assertFalse(testSquare.hasBorder(Direction.CEILING));
		assertTrue(testSquare.hasBorder(Direction.WEST));
		assertTrue(testSquare.hasBorder(Direction.FLOOR));
		assertTrue(testSquare.hasBorder(Direction.EAST));

	}
	@Test
	public final void mergeWithNewTemperatureTest(){
		testSquare.setTemperature(50);
		testSquare.setHumidity(new BigDecimal(20));
		testSquare.setBorder(Direction.NORTH,testWall);
		mergeTestSquare.setTemperature(100);
		mergeTestSquare.setHumidity(new BigDecimal(60));
		mergeTestSquare.setBorder(Direction.SOUTH,new Wall(mergeTestSquare,Direction.SOUTH));
		testSquare.mergeWith(Direction.NORTH, mergeTestSquare);
		assertEquals(85, testSquare.getTemp(),0);
	}
	@Test (expected = IllegalArgumentException.class)
	public final void setWeightConstantIllegalCaseTooBigTest(){
		Square.setWeightConstant(0.5);
	}
	@Test (expected = IllegalArgumentException.class)
	public final void setWeightConstantIllegalCaseTooSmallTest(){
		Square.setWeightConstant(0);
	}
	@Test 
	public final void setWeightConstantLegalCasetest(){
		Square.setWeightConstant(0.30);
		assertEquals(0.3,Square.getWeightConstant(),0.00000001);
	}
	@Test (expected = IllegalArgumentException.class)
	public final void mergeWithIllegalCaseNullTest(){
		testSquare.mergeWith(Direction.NORTH,null);
	}
	@Test (expected = IllegalArgumentException.class)
	public final void mergeWithIllegalCaseDirectionTest(){
		testSquare.setBorder(Direction.EAST,testDoor);
		testSquare.mergeWith(Direction.EAST,mergeTestSquare);
	}
	@Test (expected = AssertionError.class)
	public final void setHumidityIllegalTest(){
		testSquare.setHumidity(new BigDecimal(-100));
		assertEquals(20,testSquare.getHumidity().doubleValue(),0.0000001);
	}
	@Test
	public final void getTempInKelvinTest(){
		assertEquals(473.15, testSquare.getTemp(TemperatureScale.KELVIN),0);
	}
	@Test
	public final void getTempFahrenheitTest(){
		assertEquals(392, testSquare.getTemp(TemperatureScale.FAHRENHEIT),1);
	}
	@Test   (expected = IllegalArgumentException.class)
	public final void setTemperatureIllegalCaseTest(){
		testSquare.setTemperature(500000);
	}
	@Test
	public final void isValidTemperatureTrueCaseTest(){
		assertTrue(testSquare.isValidTemperature(3000,TemperatureScale.CELSIUS));
	}
	@Test
	public final void isValidTemperatureFalseCaseTooHighTest(){
		assertFalse(testSquare.isValidTemperature(5001,TemperatureScale.CELSIUS));
	}
	@Test
	public final void isValidTemperatureFalseCaseTooLowTest(){
		assertFalse(testSquare.isValidTemperature(-201,TemperatureScale.CELSIUS));
	}
	@Test
	public final void isValidHumidityLegalcaseTest(){
		assertTrue(testSquare.isValidHumidity(new BigDecimal(50)));
	}
	@Test
	public final void isValidHumidityFalseTest(){
		assertFalse(testSquare.isValidHumidity(new BigDecimal(150)));
	}

	@Test
	public final void isValidHumidityFalseTest2(){
		assertFalse(testSquare.isValidHumidity(new BigDecimal(-100)));
	}    
	@Test
	public final void canHaveAsTemperatureDomainTrueCaseTest(){
		assertTrue(testSquare.canHaveAsTemperatureDomain(-200, 100));
	}
	@Test
	public final void canHaveAsTemperatureDomainTrueCaseTest2(){
		assertTrue(testSquare.canHaveAsTemperatureDomain(-200, 200));
	}
	@Test
	public final void canHaveAsTemperatureDomainFalseCaseTest(){
		assertFalse(testSquare.canHaveAsTemperatureDomain(200, -200));
	}
	public final void setTemperatureDomainTrueCaseTest() {
		testSquare.setTemperatureDomain(-150.0, 50.0,TemperatureScale.CELSIUS,TemperatureScale.CELSIUS);
		assertEquals(-150, testSquare.getMinimumTemp(TemperatureScale.CELSIUS), 0);
		assertEquals(50.0, testSquare.getMaximumTemp(TemperatureScale.CELSIUS),0);
	}
	@Test
	public final void setTemperatureDomainTrueCaseTest2() {
		testSquare.setTemperature(-200);
		testSquare.setTemperatureDomain(-200.0, -200.0,TemperatureScale.CELSIUS,TemperatureScale.CELSIUS);
		assertEquals(-200, testSquare.getMinimumTemp(TemperatureScale.CELSIUS), 0);
		assertEquals(-200, testSquare.getMaximumTemp(TemperatureScale.CELSIUS),0);
	}
	@Test (expected = IllegalArgumentException.class)
	public final void setTemperatureDomainFalseCaseTest() {
		testSquare.setTemperatureDomain(-100.0, -500.0,TemperatureScale.CELSIUS,TemperatureScale.CELSIUS);
	}
	@Test
	public final void coldDamageLimitCaseTest(){
		testSquare.setTemperature(-14);
		assertEquals(0, testSquare.coldDamage(), 0);
	}
	@Test
	public final void ColdDamageVeryColdTest(){
		testSquare.setTemperature(-200);
		assertEquals(19, testSquare.coldDamage(), 0);
	}
	@Test
	public final void ColdDamageNoDamageTest(){
		testSquare.setTemperature(100);
		assertEquals(0, testSquare.coldDamage(), 0);
	}
	@Test
	public final void HeatDamageLimitTest(){
		testSquare.setTemperature(49);
		assertEquals(0, testSquare.heatDamage(), 0);
	}
	@Test
	public final void HeatDamageNoDamageTest(){
		testSquare.setTemperature(-150);
		assertEquals(0, testSquare.heatDamage(), 0);
	}
	@Test
	public final void HeatDamageVeryHotTest(){
		testSquare.setTemperature(200);
		assertEquals(11, testSquare.heatDamage(), 0);
	}
	@Test
	public final void RustDamageLowHumidityTest(){
		testSquare.setHumidity(new BigDecimal(0.15));
		assertEquals(0, testSquare.rustDamage(), 0);
	}
	@Test
	public final void RustDamageHighHumidityTest(){
		testSquare.setHumidity(new BigDecimal(50));
		assertEquals(2, testSquare.rustDamage(), 0);
	}
	@Test
	public final void RustDamageLimitTest(){
		testSquare.setHumidity(new BigDecimal(36));
		assertEquals(0, testSquare.rustDamage(), 0);
	}
	@Test   (expected = IllegalArgumentException.class)
	public final void setHeat_Damage_ValuesIllegalAmount1Test(){
		Square.setHeat_Damage_Values(200, -10);
	}
	@Test   (expected = IllegalArgumentException.class)
	public final void setHeat_Damage_ValuesIllegalAmount2Test(){
		Square.setHeat_Damage_Values(200, 6000);
	}
	@Test
	public final void setHeat_Damage_ValuesLegalCaseTest(){
		Square.setHeat_Damage_Values(100, 50);
		assertEquals(100, Square.getHEAT_DAMAGE_TEMPERATURE(), 0);
		assertEquals(50, Square.getHEAT_DAMAGE_RATE(), 0);
	}
	@Test
	public final void setHumidityVeryLowLegalCaseTest(){
		testSquare.setHumidity(new BigDecimal(5));
		System.out.println(testSquare.getHumidityPercentage());
		assertEquals(5, testSquare.getHumidity().doubleValue(),0);
	}
	@Test
	public final void setHumidityLegalCaseTest1(){
		testSquare.setHumidity(new BigDecimal(12.3446));
		System.out.println(testSquare.getHumidityPercentage());
		assertEquals(12.34, testSquare.getHumidity().doubleValue(),0);
	}
	@Test
	public final void setHumidityLegalCaseTest2(){
		testSquare.setHumidity(new BigDecimal(12.5678));
		System.out.println(testSquare.getHumidityPercentage());
		assertEquals(12.57, testSquare.getHumidity().doubleValue(),0);
	}
	@Test
	public final void setHumidityLegalCaseTest3(){
		testSquare.setHumidity(new BigDecimal(0.1));
		System.out.println(testSquare.getHumidityPercentage());
		assertEquals(0.10, testSquare.getHumidity().doubleValue(),0);
	}
	@Test
	public final void setHumidityLegalCaseTest4(){
		testSquare.setHumidity(BigDecimal.ZERO);
		System.out.println(testSquare.getHumidityPercentage());
		assertEquals(0.00, testSquare.getHumidity().doubleValue(),0);
	}
	@Test
	public final void setSlipperyFirstScenarioTrueTest(){
		testSquare.setHumidity(new BigDecimal(100));
		assertTrue(testSquare.isSlippery());
	}
	@Test
	public final void setSlipperySecondScenarioTrueTest(){
		testSquare.setTemperature(-20);
		testSquare.setHumidity(new BigDecimal(60));
		assertTrue(testSquare.isSlippery());
	}
	@Test
	public final void setSlipperyThirdScenarioTrueTest(){
		testSquare.setMadeOfSlipperyMaterial(true);
		assertTrue(testSquare.isSlippery());
	}
	@Test
	public final void setSlipperyFalseTest(){
		testSquare.setMadeOfSlipperyMaterial(false);
		testSquare.setHumidity(BigDecimal.ZERO	);
		testSquare.setTemperature(10);
		assertFalse(testSquare.isSlippery());
	}
	public final void mergeWithSimpleTemperatureTest(){
		testSquare.setHumidity(new BigDecimal(50));
		mergeTestSquare.setHumidity(new BigDecimal(50));
		testSquare.setTemperature(50);
		testSquare.setBorder(Direction.NORTH,testWall);
		mergeTestSquare.setTemperature(100);
		mergeTestSquare.setWall(Direction.NORTH);
		testSquare.mergeWith(Direction.NORTH,mergeTestSquare);
		assertEquals(75, testSquare.getTemp(),0);
	}
	@Test (expected = IllegalArgumentException.class)
	public final void setIllegalWeightConstantTooHighTest(){
		Square.setWeightConstant(0.5);
	}
	@Test (expected = IllegalArgumentException.class)
	public final void setIllegalWeightConstantSmallerTest(){
		Square.setWeightConstant(0);
	}
	@Test 
	public final void setlegalWeightConstantTest(){
		Square.setWeightConstant(0.3);
		assertEquals(0.3,Square.getWeightConstant(),0);
	}
	@Test (expected = IllegalArgumentException.class)
	public final void mergeWithIllegalCaseTest(){
		testSquare.mergeWith(Direction.EAST,null);
	}
	@Test 
	public final void mergeWithlegalCase2Test(){
		testSquare.setWall(Direction.CEILING);
		testSquare.mergeWith(Direction.CEILING,mergeTestSquare);
	}
	@Test (expected = AssertionError.class)
	public final void roundOffFalseTest(){
		assertEquals(30.43,testSquare.roundOff(30.438294),0.01);
	}
	@Test
	public final void roundOffTrueTest(){
		assertEquals(30.44, testSquare.roundOff(30.4382), 0.01);
	}
}